From 7700ec47f17c2f8b76b33d79b62729009a020d5d Mon Sep 17 00:00:00 2001
From: "tw275@labyrinth.cl.cam.ac.uk"
Date: Wed, 28 Jul 2004 12:13:47 +0000
Subject: [PATCH] bitkeeper revision 1.1108.29.1
(4107987b3YS7DchKHz1bWQKqXsXTsg)
Added xensv command: xensv start / stop -
checks for twisted and for xend
More work on wizzard, now persits values and can move back / forth
---
.rootkeys | 3 +
BitKeeper/etc/ignore | 11 +++
tools/misc/Makefile | 2 +-
tools/misc/xensv | 134 ++++++++++++++++++++++++++++
tools/python/xen/sv/CreateDomain.py | 19 ++--
tools/python/xen/sv/Daemon.py | 108 ++++++++++++++++++++++
tools/python/xen/sv/HTMLBase.py | 2 +-
tools/python/xen/sv/Wizzard.py | 78 ++++++++++++----
tools/python/xen/sv/params.py | 3 +
tools/python/xen/sv/util.py | 27 +++++-
10 files changed, 360 insertions(+), 27 deletions(-)
create mode 100755 tools/misc/xensv
create mode 100644 tools/python/xen/sv/Daemon.py
create mode 100644 tools/python/xen/sv/params.py
diff --git a/.rootkeys b/.rootkeys
index d09ef0e183..671bb2c25e 100644
--- a/.rootkeys
+++ b/.rootkeys
@@ -310,6 +310,7 @@
3f870808zS6T6iFhqYPGelroZlVfGQ tools/misc/xen_cpuperf.c
405eedf6_nnNhFQ1I85lhCkLK6jFGA tools/misc/xencons
40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/misc/xend
+4107986eMWVdBoz4tXYoOscpN_BCYg tools/misc/xensv
4056f5155QYZdsk-1fLdjsZPFTnlhg tools/misc/xensymoops.py
40cf2937dqM1jWW87O5OoOYND8leuA tools/misc/xm
40c9c468icGyC5RAF1bRKsCXPDCvsA tools/python/Makefile
@@ -372,6 +373,7 @@
40dc4076pVeE1kEEWzcUaNZin65kCA tools/python/xen/lowlevel/xu/domain_controller.h
40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/python/xen/lowlevel/xu/xu.c
41052eb84_irpx0E9N_kqBp9eoin5g tools/python/xen/sv/CreateDomain.py
+4107986egkTAMIHW7n-i4ShvCGWpLQ tools/python/xen/sv/Daemon.py
40fcefb2qm13BbRZBydAatOavaS0fQ tools/python/xen/sv/DomInfo.py
40fcefb2-RIU8GB67mJMRzybME9bxw tools/python/xen/sv/DomList.py
40fcefb23FfQn-ZBCbcHqA0cPGqQxw tools/python/xen/sv/GenTabbed.py
@@ -381,6 +383,7 @@
40fcefb2Sif__6AqrANeBQZZfvP-6w tools/python/xen/sv/TabView.py
41052eb8UrgtUkuJPg7oY1tutVQHsg tools/python/xen/sv/Wizzard.py
40fcefb2DqteqCCZYDCvvh4Q5jBd0w tools/python/xen/sv/__init__.py
+4107986e6qN1IdvIDdId0AYFmDMkiQ tools/python/xen/sv/params.py
40fcefb4rnaZNjqsBu7A5V2rlLyqRw tools/python/xen/sv/util.py
40d8915cyoVA0hJxiBFNymL7YvDaRg tools/python/xen/util/Brctl.py
40dfd40aGqGkiopOOgJxSF4iCbHM0Q tools/python/xen/util/__init__.py
diff --git a/BitKeeper/etc/ignore b/BitKeeper/etc/ignore
index 60cc1f1a44..46e5aff702 100644
--- a/BitKeeper/etc/ignore
+++ b/BitKeeper/etc/ignore
@@ -35,3 +35,14 @@ xen/xen.*
tools/xfrd/xfrd
xen/tools/elf-reloc
xen/tools/figlet/figlet
+docs/interface.aux
+docs/interface.log
+docs/interface.pdf
+docs/interface.ps
+docs/interface.toc
+docs/user.aux
+docs/user.log
+docs/user.pdf
+docs/user.ps
+docs/user.toc
+tools/web-shutdown.tap
diff --git a/tools/misc/Makefile b/tools/misc/Makefile
index 9795997364..2f613ea172 100644
--- a/tools/misc/Makefile
+++ b/tools/misc/Makefile
@@ -21,7 +21,7 @@ OBJS = $(patsubst %.c,%.o,$(SRCS))
TARGETS = xen_cpuperf
INSTALL_BIN = $(TARGETS) xencons
-INSTALL_SBIN = netfix xm xend
+INSTALL_SBIN = netfix xm xend xensv
all: $(TARGETS)
$(MAKE) -C miniterm
diff --git a/tools/misc/xensv b/tools/misc/xensv
new file mode 100755
index 0000000000..b877538d67
--- /dev/null
+++ b/tools/misc/xensv
@@ -0,0 +1,134 @@
+#!/usr/bin/env python
+# -*- mode: python; -*-
+#============================================================================
+# Copyright (C) 2004 Tom Wilkie
+# Copyright (C) 2004 Mike Wray
+#============================================================================
+
+"""SV web interface Lives in /usr/sbin.
+ Provides pretty HTML management interface.
+
+ Run:
+
+ sv start
+
+ The daemon is stopped with:
+
+ sv stop
+
+ The daemon will be accessible from http://localhost:8080/
+"""
+import os
+import sys
+import re
+
+from xen.xend.server.params import PID_FILE as XEND_PID_FILE
+
+class CheckError(ValueError):
+ pass
+
+def hline():
+ print >>sys.stderr, "*" * 70
+
+def msg(message):
+ print >>sys.stderr, "*" * 3, message
+
+def check_logging():
+ """Check python logging is installed and raise an error if not.
+ Logging is standard from Python 2.3 on.
+ """
+ try:
+ import logging
+ except ImportError:
+ hline()
+ msg("Python logging is not installed.")
+ msg("Use 'make install-logging' at the xen root to install.")
+ msg("")
+ msg("Alternatively download and install from")
+ msg("http://www.red-dove.com/python_logging.html")
+ hline()
+ raise CheckError("logging is not installed")
+
+def check_twisted_version():
+ """Check twisted is installed with a supported version and print a warning if not.
+ Raises an error if twisted is not installed.
+ """
+ # Supported twisted release and major version.
+ RELEASE = 1
+ MAJOR = 3
+ try:
+ from twisted.copyright import version
+ except ImportError:
+ hline()
+ msg("The Twisted framework is not installed.")
+ msg("Use 'make install-twisted' at the xen root to install.")
+ msg("")
+ msg("Alternatively download and install version %d.%d or higher" % (RELEASE, MAJOR))
+ msg("from http://www.twistedmatrix.com/products")
+ hline()
+ raise CheckError("twisted is not installed")
+
+
+ (release, major, minor) = version.split('.')
+ release = int(release)
+ major = int(major)
+ if release > RELEASE: return
+ if release == RELEASE and major >= MAJOR: return
+ hline()
+ msg("Warning: Twisted version not supported: %s" % version)
+ msg("Use Twisted version %d.%d.0 or higher" % (RELEASE, MAJOR))
+ hline()
+
+def check_xend():
+ """Check xend is running
+ """
+
+ if not os.path.isfile(XEND_PID_FILE) or not os.path.getsize(XEND_PID_FILE):
+ hline()
+ msg( "Warning: Xend has not been detected as running." )
+ msg( "Please start it immediately with: xend start " )
+ hline()
+ return 0
+
+ # Read the pid of the previous invocation and search active process list.
+ pid = open(XEND_PID_FILE, 'r').read()
+ lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
+ for line in lines:
+ if re.search('^ *' + pid + '.+xend', line):
+ return 1
+
+ hline()
+ msg( "Warning: Xend has not been detected as running." )
+ msg( "Please start it immediately with: xend start " )
+ hline()
+ return 0
+
+def main():
+ try:
+ check_logging()
+ check_twisted_version()
+ check_xend()
+ except CheckError:
+ sys.exit(1)
+
+ from xen.sv import Daemon
+
+ daemon = Daemon.instance()
+
+ if not sys.argv[1:]:
+ print 'usage: %s {start|stop|restart}' % sys.argv[0]
+ elif os.fork():
+ pid, status = os.wait()
+ return status >> 8
+ elif sys.argv[1] == 'start':
+ return daemon.start()
+ elif sys.argv[1] == 'stop':
+ return daemon.stop()
+ elif sys.argv[1] == 'restart':
+ return daemon.stop() or daemon.start()
+ else:
+ print 'not an option:', sys.argv[1]
+ return 1
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/tools/python/xen/sv/CreateDomain.py b/tools/python/xen/sv/CreateDomain.py
index 13c45d8622..62c6fe9d5b 100644
--- a/tools/python/xen/sv/CreateDomain.py
+++ b/tools/python/xen/sv/CreateDomain.py
@@ -14,30 +14,33 @@ class CreatePage0( Sheet ):
def __init__( self, urlWriter ):
- feilds = [( 'name', 'Name')]
+ feilds = [( 'name', 'VM Name:'),
+ ( 'memory', 'RAM (Mb):' )]
- Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 1" )
+ Sheet.__init__( self, urlWriter, feilds, "Create New Domain", 0 )
class CreatePage1( Sheet ):
def __init__( self, urlWriter ):
- feilds = [( 'name', 'Name')]
+ feilds = [( 'kernel_type', 'Kernel Type:'),
+ ( 'kernel_location', 'Kernel location:')]
- Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 2" )
+ Sheet.__init__( self, urlWriter, feilds, "Setup Kernel Image", 1 )
class CreatePage2( Sheet ):
def __init__( self, urlWriter ):
- feilds = [( 'name', 'Name')]
+ feilds = [( 'vbd_dom0', 'Location of vbd:'),
+ ( 'vbd_dom0', 'Vitualised location:')]
- Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 3" )
+ Sheet.__init__( self, urlWriter, feilds, "Setup Virtual Block Devices", 2 )
class CreatePage3( Sheet ):
def __init__( self, urlWriter ):
- feilds = [( 'name', 'Name')]
+ feilds = [( 'vifs', 'Number of Vifs:')]
- Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 4" )
\ No newline at end of file
+ Sheet.__init__( self, urlWriter, feilds, "Create New Domain - 4", 3 )
diff --git a/tools/python/xen/sv/Daemon.py b/tools/python/xen/sv/Daemon.py
new file mode 100644
index 0000000000..fdbc6145dc
--- /dev/null
+++ b/tools/python/xen/sv/Daemon.py
@@ -0,0 +1,108 @@
+###########################################################
+## XenSV Web Control Interface Daemon
+## Copyright (C) 2004, K A Fraser (University of Cambridge)
+## Copyright (C) 2004, Mike Wray
+## Copyright (C) 2004, Tom Wilkie
+###########################################################
+
+import os
+import os.path
+import sys
+import re
+
+from xen.sv.params import *
+
+from twisted.internet import reactor
+from twisted.web import static, server, script
+
+class Daemon:
+ """The xend daemon.
+ """
+ def __init__(self):
+ self.shutdown = 0
+ self.traceon = 0
+
+ def daemon_pids(self):
+ pids = []
+ pidex = '(?P\d+)'
+ pythonex = '(?P\S*python\S*)'
+ cmdex = '(?P.*)'
+ procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$')
+ xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$')
+ procs = os.popen('ps -e -o pid,args 2>/dev/null')
+ for proc in procs:
+ pm = procre.match(proc)
+ if not pm: continue
+ xm = xendre.match(pm.group('cmd'))
+ if not xm: continue
+ #print 'pid=', pm.group('pid'), 'cmd=', pm.group('cmd')
+ pids.append(int(pm.group('pid')))
+ return pids
+
+ def new_cleanup(self, kill=0):
+ err = 0
+ pids = self.daemon_pids()
+ if kill:
+ for pid in pids:
+ print "Killing daemon pid=%d" % pid
+ os.kill(pid, signal.SIGHUP)
+ elif pids:
+ err = 1
+ print "Daemon already running: ", pids
+ return err
+
+ def cleanup(self, kill=False):
+ # No cleanup to do if PID_FILE is empty.
+ if not os.path.isfile(PID_FILE) or not os.path.getsize(PID_FILE):
+ return 0
+ # Read the pid of the previous invocation and search active process list.
+ pid = open(PID_FILE, 'r').read()
+ lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
+ for line in lines:
+ if re.search('^ *' + pid + '.+xensv', line):
+ if not kill:
+ print "Daemon is already running (pid %d)" % int(pid)
+ return 1
+ # Old daemon is still active: terminate it.
+ os.kill(int(pid), 1)
+ # Delete the stale PID_FILE.
+ os.remove(PID_FILE)
+ return 0
+
+ def start(self, trace=0):
+ if self.cleanup(kill=False):
+ return 1
+
+ # Fork -- parent writes PID_FILE and exits.
+ pid = os.fork()
+ if pid:
+ # Parent
+ pidfile = open(PID_FILE, 'w')
+ pidfile.write(str(pid))
+ pidfile.close()
+ return 0
+ # Child
+ self.run()
+ return 0
+
+ def stop(self):
+ return self.cleanup(kill=True)
+
+ def run(self):
+ root = static.File( SV_ROOT )
+ root.indexNames = [ 'Main.rpy' ]
+ root.processors = { '.rpy': script.ResourceScript }
+ reactor.listenTCP( SV_PORT, server.Site( root ) )
+ reactor.run()
+
+ def exit(self):
+ reactor.diconnectAll()
+ sys.exit(0)
+
+def instance():
+ global inst
+ try:
+ inst
+ except:
+ inst = Daemon()
+ return inst
diff --git a/tools/python/xen/sv/HTMLBase.py b/tools/python/xen/sv/HTMLBase.py
index 7c500e8a2b..07adfab76d 100755
--- a/tools/python/xen/sv/HTMLBase.py
+++ b/tools/python/xen/sv/HTMLBase.py
@@ -25,9 +25,9 @@ class HTMLBase( Resource ):
request.write( 'Xen ' )
request.write( '' )
request.write( '' )
+ request.write('')
request.write( "" )
diff --git a/tools/python/xen/sv/Wizzard.py b/tools/python/xen/sv/Wizzard.py
index 0f506d03b8..eaec7592b6 100755
--- a/tools/python/xen/sv/Wizzard.py
+++ b/tools/python/xen/sv/Wizzard.py
@@ -2,13 +2,14 @@ from xen.sv.util import *
from xen.sv.HTMLBase import HTMLBase
from xen.xend import sxp
+DEBUG = 1
+
class Wizzard( HTMLBase ):
def __init__( self, urlWriter, title, sheets ):
HTMLBase.__init__( self )
self.title = title
self.sheets = sheets
- self.currSheet = 0
self.urlWriter = urlWriter
def write_MENU( self, request ):
@@ -22,45 +23,90 @@ class Wizzard( HTMLBase ):
currSheet = getVar( 'sheet', request )
if not currSheet is None:
+ currSheet = int( currSheet )
+ else:
+ currSheet = 0
+
+ op = getVar( 'op', request )
- self.currSheet = int( currSheet )
+ if op == 'next':
+ currSheet += 1
+ elif op == 'prev':
+ currSheet -= 1
- self.sheets[ self.currSheet ]( self.urlWriter ).write_BODY( request )
+ self.sheets[ currSheet ]( self.urlWriter ).write_BODY( request )
request.write( "" )
- request.write( "" )
- request.write( " " )
- request.write( "
" )
- request.write( "
" )
+ request.write( "" )
+ if currSheet > 0:
+ request.write( " " )
+ if currSheet < ( len( self.sheets ) - 1 ):
+ request.write( " " )
+ request.write( "
" )
request.write( "" )
+ def op_next( self, request ):
+ pass
+
+ def op_prev( self, request ):
+ pass
+
class Sheet( HTMLBase ):
- def __init__( self, urlWriter, feilds, title ):
+ def __init__( self, urlWriter, feilds, title, location ):
HTMLBase.__init__( self )
self.urlWriter = urlWriter
self.feilds = feilds
self.title = title
+ self.location = location
+ self.passback = "()"
def parseForm( self, request ):
- return sxp.toString( request.args )
+ do_not_parse = [ 'mod', 'op', 'sheet' ]
+
+ passed_back = request.args
+
+ temp_passback = passed_back.get( "passback" )
+
+ if temp_passback is not None and len( temp_passback ) > 0:
+ temp_passback = temp_passback[ len( temp_passback )-1 ]
+ else:
+ temp_passback = "(passback )"
+
+ last_passback = ssxp2hash( string2sxp( temp_passback ) )
+
+ if DEBUG: print last_passback
+
+ try:
+ del passed_back[ 'passback' ]
+ except:
+ pass
+
+ for (key, value) in passed_back.items():
+ if key not in do_not_parse:
+ last_passback[ key ] = value[ len( value ) - 1 ]
+
+ self.passback = sxp2string( hash2sxp( last_passback ) ) #store the sxp
+
+ if DEBUG: print self.passback
+
+ return last_passback #return the hash
def write_BODY( self, request ):
+
request.write( "%s
" % self.title )
- previous_values = request.args
+ previous_values = self.parseForm( request ) #get the hash for quick reference
for (feild, name) in self.feilds:
- value = sxp.child_value( previous_values, feild )
+ value = previous_values.get( feild )
if value is None:
value = ''
request.write( "%s
" % (name, feild, value) )
-
- def op_next( self, request ):
- pass
- def op_prev( self, request ):
- pass
+ request.write( "
" % self.passback )
+ request.write( " " % self.location )
+
diff --git a/tools/python/xen/sv/params.py b/tools/python/xen/sv/params.py
new file mode 100644
index 0000000000..16b764f088
--- /dev/null
+++ b/tools/python/xen/sv/params.py
@@ -0,0 +1,3 @@
+SV_PORT = 8080
+SV_ROOT = "/var/xen/sv/"
+PID_FILE = "/var/xen/sv.pid"
\ No newline at end of file
diff --git a/tools/python/xen/sv/util.py b/tools/python/xen/sv/util.py
index adf75b073c..c14137609f 100755
--- a/tools/python/xen/sv/util.py
+++ b/tools/python/xen/sv/util.py
@@ -18,7 +18,32 @@ def sxp2hash( s ):
else:
sxphash[ child[0] ] = child[1]
- return sxphash
+ return sxphash
+
+def ssxp2hash( s ):
+ sxphash = {}
+
+ for i in s:
+ if isinstance( i, types.ListType ) and len( i ) > 1:
+ sxphash[ i[0] ] = i[1]
+
+ return sxphash
+
+def hash2sxp( h ):
+ hashsxp = []
+
+ for (key, item) in h.items():
+ hashsxp.append( [key, item] )
+
+ return hashsxp
+
+def string2sxp( string ):
+ pin = sxp.Parser()
+ pin.input( string )
+ return pin.get_val()
+
+def sxp2string( sexp ):
+ return sxp.to_string( sexp )
def sxp2prettystring( sxp ):
class tmp:
--
2.30.2